using Microsoft.AspNetCore.SignalR;
using WMS_Goodsinfo.Api.Write.DTOs;
using WMS_Goodsinfo.Api.Write.Hubs;

namespace WMS_Goodsinfo.Api.Write.Services
{
    /// <summary>
    /// 仪表板实时数据推送后台服务
    /// </summary>
    public class DashboardRealtimeService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IHubContext<DashboardRealtimeHub> _hubContext;
        private readonly ILogger<DashboardRealtimeService> _logger;

        // 推送间隔配置
        private readonly int _highFrequencyInterval = 10000; // 10秒 - 入库出库统计
        private readonly int _mediumFrequencyInterval = 10000; // 30秒 - 排行榜
        private readonly int _lowFrequencyInterval = 10000; // 30秒 - 库存占比
        private readonly int _messageCheckInterval = 10000; // 1分钟 - 系统消息检查

        private DateTime _lastMediumFrequencyPush = DateTime.MinValue;
        private DateTime _lastLowFrequencyPush = DateTime.MinValue;
        private DateTime _lastMessageCheck = DateTime.MinValue;

        public DashboardRealtimeService(
            IServiceProvider serviceProvider,
            IHubContext<DashboardRealtimeHub> hubContext,
            ILogger<DashboardRealtimeService> logger)
        {
            _serviceProvider = serviceProvider;
            _hubContext = hubContext;
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("仪表板实时数据推送服务启动");

            // 等待5秒让应用完全启动
            await Task.Delay(5000, stoppingToken);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var now = DateTime.Now;

                    // 高频推送：每10秒推送入库出库统计
                    await PushHighFrequencyData();

                    // 中频推送：每30秒推送排行榜数据
                    if (ShouldPushMediumFrequency(now))
                    {
                        await PushMediumFrequencyData();
                        _lastMediumFrequencyPush = now;
                    }

                    // 低频推送：每5分钟推送库存占比
                    if (ShouldPushLowFrequency(now))
                    {
                        await PushLowFrequencyData();
                        _lastLowFrequencyPush = now;
                    }

                    // 消息检查：每1分钟检查系统消息
                    if (ShouldCheckMessages(now))
                    {
                        await CheckAndPushMessages();
                        _lastMessageCheck = now;
                    }

                    _logger.LogDebug($"仪表板数据推送完成 - {now:yyyy-MM-dd HH:mm:ss}");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "仪表板数据推送失败");
                }

                // 等待下一次推送
                await Task.Delay(_highFrequencyInterval, stoppingToken);
            }

            _logger.LogInformation("仪表板实时数据推送服务停止");
        }

        /// <summary>
        /// 高频推送：入库出库统计数据
        /// </summary>
        private async Task PushHighFrequencyData()
        {
            try
            {
                // 分别获取入库和出库数据，避免并发访问同一个DbContext
                InboundStatisticsData inboundData;
                OutboundStatisticsData outboundData;

                using (var scope1 = _serviceProvider.CreateScope())
                {
                    var statisticsService1 = scope1.ServiceProvider.GetRequiredService<IDashboardStatisticsService>();
                    inboundData = await statisticsService1.GetInboundStatisticsAsync();
                }

                using (var scope2 = _serviceProvider.CreateScope())
                {
                    var statisticsService2 = scope2.ServiceProvider.GetRequiredService<IDashboardStatisticsService>();
                    outboundData = await statisticsService2.GetOutboundStatisticsAsync();
                }

                // 推送到所有连接的客户端
                var pushTasks = new[]
                {
                    _hubContext.Clients.Group("Dashboard").SendAsync("ReceiveInboundStatistics", inboundData),
                    _hubContext.Clients.Group("Dashboard").SendAsync("ReceiveOutboundStatistics", outboundData)
                };

                await Task.WhenAll(pushTasks);

                _logger.LogDebug("高频数据推送完成：入库出库统计");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "高频数据推送失败");
            }
        }

        /// <summary>
        /// 中频推送：排行榜数据
        /// </summary>
        private async Task PushMediumFrequencyData()
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var statisticsService = scope.ServiceProvider.GetRequiredService<IDashboardStatisticsService>();

                var rankingData = await statisticsService.GetRankingDataAsync();

                await _hubContext.Clients.Group("Dashboard")
                    .SendAsync("ReceiveRankingData", rankingData);

                _logger.LogDebug("中频数据推送完成：排行榜");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "中频数据推送失败");
            }
        }

        /// <summary>
        /// 低频推送：库存占比数据
        /// </summary>
        private async Task PushLowFrequencyData()
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var statisticsService = scope.ServiceProvider.GetRequiredService<IDashboardStatisticsService>();

                var inventoryData = await statisticsService.GetInventoryProportionAsync();

                await _hubContext.Clients.Group("Dashboard")
                    .SendAsync("ReceiveInventoryProportion", inventoryData);

                _logger.LogDebug("低频数据推送完成：库存占比");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "低频数据推送失败");
            }
        }

        /// <summary>
        /// 检查并推送系统消息
        /// </summary>
        private async Task CheckAndPushMessages()
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var statisticsService = scope.ServiceProvider.GetRequiredService<IDashboardStatisticsService>();

                var messages = await statisticsService.CheckSystemMessagesAsync();

                if (messages.Any())
                {
                    await _hubContext.Clients.Group("Dashboard")
                        .SendAsync("ReceiveSystemMessages", messages);

                    _logger.LogDebug($"系统消息推送完成：{messages.Count}条消息");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "系统消息检查推送失败");
            }
        }

        /// <summary>
        /// 是否应该推送中频数据
        /// </summary>
        private bool ShouldPushMediumFrequency(DateTime now)
        {
            return (now - _lastMediumFrequencyPush).TotalMilliseconds >= _mediumFrequencyInterval;
        }

        /// <summary>
        /// 是否应该推送低频数据
        /// </summary>
        private bool ShouldPushLowFrequency(DateTime now)
        {
            return (now - _lastLowFrequencyPush).TotalMilliseconds >= _lowFrequencyInterval;
        }

        /// <summary>
        /// 是否应该检查消息
        /// </summary>
        private bool ShouldCheckMessages(DateTime now)
        {
            return (now - _lastMessageCheck).TotalMilliseconds >= _messageCheckInterval;
        }

        /// <summary>
        /// 服务停止时的清理工作
        /// </summary>
        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("正在停止仪表板实时数据推送服务...");

            try
            {
                // 通知所有客户端服务即将停止
                await _hubContext.Clients.All.SendAsync("ServiceStopping", "仪表板数据推送服务即将停止", cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "通知客户端服务停止时出错");
            }

            await base.StopAsync(cancellationToken);
            _logger.LogInformation("仪表板实时数据推送服务已停止");
        }
    }
}